
import main_aux
from importpyrind import pyrind
import shellclasses
import mutil
import os
import toolpalette
Callable = pyrind.wrappers.Callable 
	
class MeringueMain(main_aux.MainAux):
	mapTkWidgetsToModelObjects = None
	selectedModelObject = None
	filepath=None
	supportedObjs=(('Button',shellclasses.MeringueProjectButton), 
			('Input',shellclasses.MeringueProjectInput),
			('Checkbox',shellclasses.MeringueProjectCheckbox),
			('Field',shellclasses.MeringueProjectField),
			('Label',shellclasses.MeringueProjectLabel),
			('Listbox',shellclasses.MeringueProjectListbox),) 
	def __init__(self,w):
		
		self.window = w
		self.mapTkWidgetsToModelObjects = {}
		self.selectedModelObject = None
		self.selectedPyrObject = None
		
		#create tool pallete
		self.toolPalette = toolpalette.ToolPalette(self) #yeah, a a circular reference here...
		self.toolPalette.launch(self.window._basecontrol)
		
		w.title = 'Meringue - Untitled'
		self.topframe = w.begin_frame(fill=True, resizable=True)
		
		self.addMenuBar(w)
		self.addContextButtons()
		w.end_frame()
		self.newProject('Untitled')
		
		
		self.window._basecontrol.lift()
		
		w.start()
	
	
	def newProject(self, name=None):
		if name==None:
			name = pyrind.dialog.ask('Enter name of project (alphanum):', 'test', title="Name of project")
			if not name: return
		shortname = mutil.makeIdentifier(name)
		if not shortname: return
		self.filepath = None
		
		self.objectModel = shellclasses.MeringueProjectShell()
		self.objectModel.projectName = shortname
		self.objectModel.title = name
		self._loadModel()
	
	def openProject(self):
		file = pyrind.dialog.ask_openfile(initialfolder='.',title='Open',types=['.mng|Meringue project'])
		if not file: return
		import pickle
		f=open(file,'rb')
		newmodel = pickle.load(f)
		f.close()
		self.filepath = file
		
		self.objectModel = newmodel
		self._loadModel()
	
	def _loadModel(self):
		self.window._basecontrol.geometry('%dx%d'%(self.objectModel.width, self.objectModel.height))
		
		#clear existing widgets
		for widget in self.mapTkWidgetsToModelObjects:
			widget.unadd()
			widget.delete()
		self.mapTkWidgetsToModelObjects = {}
		
		self.window.title = 'Meringue - '+self.objectModel.projectName
		self.toolPalette.openFirstTab()
		self.toolPalette.refreshFrame()
		#draw new widgets
		for widgetmodel in self.objectModel.widgets:
			self.addModelWidgetToForm(widgetmodel)
		
		#add binding to window itself
		self.topframe._basecontrol.bind('<Button-1>', self.onclickWindow)
		self.selectedModelObject = self.objectModel.window
		self.selectedPyrObject = self.window
		
	def onclickWindow(self, e=None):
		#deselect everything
		for pyrobj in self.mapTkWidgetsToModelObjects:
			pyrobj.borderwidth = 1
		self.selectedModelObject = self.objectModel.window
		self.selectedPyrObject = self.window
		self.hideContextButtons()
		self.toolPalette.refreshFrame()
		self.window.focus()
		
	def addModelWidgetToForm(self, widgetmodel):
		classObj = mutil.textToClass[ widgetmodel.pyrindClassName] #get a pyrind class object
		newPyrindObj = classObj(parent=self.topframe, **widgetmodel.pyrindProperties)
		newPyrindObj.add(position=(widgetmodel.coordLeft,widgetmodel.coordTop))
		self.mapTkWidgetsToModelObjects[ newPyrindObj ] = widgetmodel
		#add 'select' binding
		newPyrindObj._basecontrol.bind('<Button-1>', Callable(self.onclickWidget,newPyrindObj))
		return newPyrindObj
	def onclickWidget(self, pyrindObj):
		self.selectWidget(pyrindObj)
	def selectWidget(self, pyrindObj):
		#make all the rest normal:
		for pyrobj in self.mapTkWidgetsToModelObjects:
			pyrobj.borderwidth = 1
		pyrindObj.borderwidth = 4 #show that it's selected
		#.winfo_width() may be useful if doing something more fancy here.
		self.selectedModelObject = self.mapTkWidgetsToModelObjects[pyrindObj]
		self.selectedPyrObject = pyrindObj
		self.toolPalette.refreshFrame()
		#now show those fancy btns with options
		self.showContextButtons(pyrindObj)
	def getSelected(self):
		return self.selectedModelObject
	def updateSelectionProps(self):
		filteredDict = {}
		#hack-- based on ' '*8
		for k in self.selectedModelObject.pyrindProperties:
			if self.selectedModelObject.pyrindProperties[k]!=' '*8:
				filteredDict[k] = self.selectedModelObject.pyrindProperties[k]
		self.selectedPyrObject.set_many(**filteredDict)
		
	def removeSelectedWidget(self):
		if self.selectedModelObject==self.objectModel.window or self.selectedModelObject==None: return
		target, targetPyr = self.selectedModelObject, self.selectedPyrObject
		self.onclickWindow() #deselect everything
		del self.mapTkWidgetsToModelObjects[targetPyr]
		self.objectModel.widgets.remove(target) #linear search for target and removes it
		targetPyr.unadd(); targetPyr.delete()
		
	
	def createNewWidgetFromPalette(self, oclass): #where oclass is a modelObject class object
		sTypeName = oclass.pyrindClassName[1:] #RButton->Button todo: hack
		#let's give it a name like "button2"
		#first count how many others of this type exist
		count = 0
		for pyrobj in self.mapTkWidgetsToModelObjects:
			if isinstance(self.mapTkWidgetsToModelObjects[pyrobj], oclass):
				count += 1
		
		sname = sTypeName+str(count + 1) #i.e. "button2"
		newObject = oclass(sname)
		if oclass in (shellclasses.MeringueProjectButton,shellclasses.MeringueProjectLabel,shellclasses.MeringueProjectCheckbox):
			newObject.pyrindProperties['text'] = sname
		#todo: transfer some settings from the real object to the model object?
		#~ if oclass==shellclasses.MeringueProjectListbox or oclass==shellclasses.MeringueProjectField:
			#~ newObject.pyrindProperties['scrollbar'] = True
		if oclass==shellclasses.MeringueProjectField:
			newObject.pyrindProperties['width'] = 15
			newObject.pyrindProperties['height'] = 4
		if oclass==shellclasses.MeringueProjectListbox:
			newObject.pyrindProperties['width'] = 15
			newObject.pyrindProperties['height'] = 4
			newObject.pyrindProperties['items'] = ['1','2','3']
			
		newObject.coordLeft = 300;newObject.coordTop = 300;
		
		
		#add it to main model
		self.objectModel.widgets.append(newObject)
		#render it on form
		pyrObject = self.addModelWidgetToForm(newObject)
		self.selectWidget(pyrObject)
	
	
	
	
	
	def notImpl(self): pyrind.dialog.alert('Not yet implemented.')
	def helpAbout(self): pyrind.dialog.alert('Meringue 0.2\nBy Ben Fisher, 2009\n\n')
	def saveProject(self):
		# save window size
		self.objectModel.width = self.topframe._basecontrol.winfo_width()
		self.objectModel.height = self.topframe._basecontrol.winfo_height()
		
		if self.filepath == None:
			file = pyrind.dialog.ask_savefile(initialfolder='.',title='Save As',types=['.mng|Meringue project'])
			if not file: return
		else:
			file = self.filepath
		import pickle
		f=open(file,'wb')
		pickle.dump( self.objectModel,f)
		f.close()
		self.filepath = file
		return True
	
	def runProject(self):
		if self.filepath == None: 
			if not self.saveProject():
				return
		dir, fname = os.path.split(self.filepath)
		outname = os.path.join(dir, fname.replace('.mng', '_gen.py'))
		outcodename = os.path.join(dir, fname.replace('.mng', '_code.py'))
		
		s = shellclasses.renderShellClassToPython(self.objectModel, fname.replace('.mng', '_code'))
		shellclasses.renderCodeImplToPython(self.objectModel,outcodename)
		f=open(outname,'wb')
		f.write(s)
		f.close()
		return fname.replace('.mng', '_gen.py')
		
		
app = MeringueMain(pyrind.RWindow())

#todo: draw context buttons on top of everything else.
